Questions
12 of 14
1What is a segment in Qdrant's storage engine, and why does a collection consist of multiple segments rather than one monolithic index?
2What role does the Write-Ahead Log (WAL) play in Qdrant, and what failure scenario does it protect against?
3How does memory-mapped (mmap) storage allow Qdrant to serve a collection larger than available RAM?
4What does the background optimizer do in Qdrant, and why can too-aggressive optimization affect query latency?
5What is the practical difference between storing vectors in-memory versus on-disk in a collection configuration, and when would you choose on-disk?
6What is sharding in a distributed Qdrant cluster, and what determines which shard a given point is written to by default?
7What is custom sharding, and how does it change the way multitenant data is distributed across a cluster?
8What consensus algorithm does Qdrant use to keep cluster metadata consistent across nodes, and what does it coordinate?
9What are Qdrant's tunable read/write consistency levels for distributed operations, and what trade-off do they represent?
10In a replicated cluster, what happens to search results if a query is served while one replica of a shard is temporarily out of sync?
11Walk through what happens internally, at a high level, when a client sends a filtered vector search request to a distributed Qdrant cluster.
12Why does Qdrant merge and re-rank results from multiple shards rather than simply concatenating each shard's top-k?
13How does a payload filter interact with segment selection during query execution - does Qdrant always scan every segment?
14What is the performance implication of running a query that touches every named vector on a point versus one that specifies using?
12 / 14

Why does Qdrant merge and re-rank results from multiple shards rather than simply concatenating each shard's top-k?

Each shard only sees a subset, so a global top-k requires merging

Because each shard holds only a subset of the collection's points, a shard's top-k is the top-k within that subset, not within the whole collection. If you simply concatenated the per-shard top-k lists, you would get a list of k times shard_count candidates, and the true global nearest neighbors could be ranked below candidates that happened to be in the same shard as each other. The correct global top-k requires two things: each shard must return more than k candidates (at least k plus any offset, and often more to account for the fact that the global ranking can pull from any shard), and the coordinator must merge the candidate sets by score and take the global top-k. This is the standard distributed top-k merge, and it is the only way to get the same result you would get from a single-shard search.

The mechanism is straightforward but easy to get wrong. The coordinator sends the query to every relevant shard with a per-shard limit that is at least the global limit plus the offset. If the query has offset=100 and limit=10, each shard must return 110 results, because the global 11th through 110th results could all come from a single shard. If the query involves a fusion stage (for example, Reciprocal Rank Fusion of a dense and sparse retriever), the merge is not a score sort but a rank-based fusion: the coordinator fuses the per-shard lists before taking the global top-k. This is why the fusion semantics matter: merging by score and merging by rank produce different results, and the coordinator has to apply the same fusion that a single-shard query would. For multi-stage queries expressed with prefetch, each stage's merge happens at the coordinator, and the candidate set passed to the next stage is the merged result, not the concatenation of per-shard lists.

  1. 1

    Per-shard limit must be at least global limit + offset, or the global top-k can be wrong.

  2. 2

    Merge is by score for a single-stage query, or by the fusion function (e.g. RRF) for a hybrid query.

  3. 3

    Concatenation is wrong: it can put a shard's local top-1 above the true global top-1.

  4. 4

    Multi-stage queries merge at each stage; the candidate set for the next stage is the merged result.

  5. 5

    The coordinator's merge cost grows with shard count and with the per-shard limit, which is why shard count is a tuning parameter.

The trade-off is result correctness against coordinator cost. Requesting more than k from each shard is necessary for correctness but increases the data transferred to the coordinator and the cost of the merge. The coordinator's work is proportional to shard_count times per_shard_limit, so at high shard counts and large limits the merge itself becomes a bottleneck. The common mistake is thinking that concatenating per-shard top-k is a reasonable approximation. It is not - it can systematically favor shards that happen to contain many similar points, and the error is not bounded. The second mistake is forgetting the offset. A query with offset=1000 and limit=10 that requests only 10 per shard will return the wrong results, because the global top-1010 almost certainly includes more than 10 results from at least one shard. The third mistake is applying a score-based merge to a hybrid query that used rank-based fusion on the shards; the merge must use the same fusion function. Version note: the prefetch/fusion API and the exact merge semantics for multi-stage queries are recent additions and have changed across releases; the coordinator's behavior under fusion is version-specific.

javascript

Version-dependent: the prefetch and fusion API, the supported fusion modes (RRF, DBSF), and the exact merge semantics at each stage have evolved across releases. In older versions, multi-stage retrieval was orchestrated in the application layer, which meant the merge happened in the client and the per-shard limit was your responsibility. In newer versions, the coordinator handles the nesting, and the per-shard limit is derived from the stage's limit. If you are debugging a result discrepancy between a single-shard and multi-shard deployment, check the version's merge behavior first, because it is the most likely source of a subtle difference.

Difficulty: 8/10
Topics: Query Execution, Distributed Architecture, Fusion

Scenario Questions

0-2 years experience
  1. 1

    You have a 4-shard collection and query with limit=10 without offset. Explain why each shard returns 10 results and why the coordinator does not just concatenate them.

  2. 2

    A teammate implements a client-side merge by concatenating per-shard results. Explain what is wrong with that.

2-5 years experience
  1. 1

    You run a query with offset=500 and limit=10 on an 8-shard collection. Explain how many results each shard must return and what happens if Qdrant requested only 10.

  2. 2

    You compare results from a 1-shard and an 8-shard deployment of the same data and they differ. Diagnose whether the merge is the cause and how you would confirm.

5-8 years experience
  1. 1

    Design a hybrid retrieval pipeline with dense and sparse prefetch, RRF fusion, and a reranker, on a 16-shard collection. Explain where the merge happens at each stage and how you would validate correctness.

  2. 2

    Your coordinator is CPU-bound during merges at high QPS. Explain the cost model and propose two ways to reduce the merge cost without changing the shard count.

8+ years experience
  1. 1

    Derive the minimum per-shard limit required for a correct global top-k as a function of shard count, global limit, and offset, and explain when the bound is tight versus loose.

  2. 2

    You are designing a query coordinator for a sharded vector search system. Describe the merge algorithm, its complexity, and how you would handle a shard that returns late or fails entirely.

Follow-up Questions

  • How would you prove that Qdrant's merge is correct for a specific query and shard layout, and what would a counterexample of incorrect concatenation look like?
  • What is the coordinator's merge cost as a function of shard count and per-shard limit, and at what point does it become the bottleneck?